﻿using System.Windows.Media;
using ff14bot;
using ff14bot.Helpers;
using ff14bot.Managers;
using ff14bot.Enums;
using MoreDots.Rotations.Classes;
using MoreDots.SpellNames;
using MoreDots.SpellNames.Jobs;
using System.Threading.Tasks;
using ff14bot.Objects;
using System.Linq;
using System.Collections.Generic;
using MoreDots.SpellNames.Classes;
using Buddy.Coroutines;

namespace MoreDots.Rotations.Jobs
{
    public class Bard : Archer
    {
        public override string Name { get { return "MoreDots [" + GetType().Name + "]"; } }
        public override ClassJobType[] Class { get { return new ClassJobType[] { ClassJobType.Bard }; } }

        #region Lower LvL Rotations
        public override async Task<bool> CombatLvL1()
        {
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL2()
        {
            if (await StraightShot()) return true;

            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL4()
        {
            if (await Featherfoot()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await StraightShot()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL6()
        {
            if (await Featherfoot()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await StraightShot()) return true;
            if (await VenomousBite()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL8()
        {
            if (await Featherfoot()) return true;
            if (await SecondWind()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await StraightShot()) return true;
            if (await MiserysEnd()) return true;
            if (await VenomousBite()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL10()
        {
            if (await Featherfoot()) return true;
            if (await SecondWind()) return true;
            if (await Shadowbind()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await StraightShot()) return true;
            if (await MiserysEnd()) return true;
            if (await VenomousBite()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL12()
        {
            if (await Featherfoot()) return true;
            if (await SecondWind()) return true;
            if (await Shadowbind()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await BardSpells.CrossClass.InternalRelease.Buff()) return true;
            if (await StraightShot()) return true;
            if (await MiserysEnd()) return true;
            if (await Bloodletter()) return true;
            if (await VenomousBite()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL14() { return await CombatLvL12(); }
        public override async Task<bool> CombatLvL16() { return await CombatLvL12(); }
        public override async Task<bool> CombatLvL18()
        {
            if (await Featherfoot()) return true;
            if (await SecondWind()) return true;
            if (await Shadowbind()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await BardSpells.CrossClass.InternalRelease.Buff()) return true;
            if (await StraightShot()) return true;
            if (await MiserysEnd()) return true;
            if (await Bloodletter()) return true;
            if (await QuickNock()) return true;
            if (await VenomousBite()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL20() { return await CombatLvL18(); }
        public override async Task<bool> CombatLvL22() { return await CombatLvL18(); }
        public override async Task<bool> CombatLvL24() { return await CombatLvL18(); }
        public override async Task<bool> CombatLvL26()
        {
            if (await Featherfoot()) return true;
            if (await SecondWind()) return true;
            if (await Invigorate()) return true;
            if (await Shadowbind()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await BardSpells.HawksEye.Buff()) return true;
            if (await BardSpells.CrossClass.InternalRelease.Buff()) return true;
            if (await StraightShot()) return true;
            if (await MiserysEnd()) return true;
            if (await Bloodletter()) return true;
            if (await QuickNock()) return true;
            if (await VenomousBite()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL28() { return await CombatLvL26(); }
        public override async Task<bool> CombatLvL30()
        {
            if (await Featherfoot()) return true;
            if (await SecondWind()) return true;
            if (await Invigorate()) return true;
            if (await Shadowbind()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await BardSpells.HawksEye.Buff()) return true;
            if (await BardSpells.CrossClass.InternalRelease.Buff()) return true;
            if (await StraightShot()) return true;
            if (await MiserysEnd()) return true;
            if (await Bloodletter()) return true;
            if (await QuickNock()) return true;
            if (await VenomousBite()) return true;
            if (await WindBite()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL32() { return await CombatLvL30(); }
        public override async Task<bool> CombatLvL34()
        {
            if (await Featherfoot()) return true;
            if (await SecondWind()) return true;
            if (await Invigorate()) return true;
            if (await Shadowbind()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await BardSpells.HawksEye.Buff()) return true;
            if (await BardSpells.CrossClass.InternalRelease.Buff()) return true;
            if (await BardSpells.CrossClass.BloodForBlood.Buff()) return true;
            if (await BardSpells.QuellingStrikes.Buff()) return true;
            if (await StraightShot()) return true;
            if (await MiserysEnd()) return true;
            if (await Bloodletter()) return true;
            if (await QuickNock()) return true;
            if (await VenomousBite()) return true;
            if (await WindBite()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL36() { return await CombatLvL34(); }
        public override async Task<bool> CombatLvL38() { return await CombatLvL34(); }
        public override async Task<bool> CombatLvL40()
        {
            if (await Featherfoot()) return true;
            if (await SecondWind()) return true;
            if (await Invigorate()) return true;
            if (await Shadowbind()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await BardSpells.HawksEye.Buff()) return true;
            if (await BardSpells.Barrage.Buff()) return true;
            if (await BardSpells.CrossClass.InternalRelease.Buff()) return true;
            if (await BardSpells.CrossClass.BloodForBlood.Buff()) return true;
            if (await BardSpells.QuellingStrikes.Buff()) return true;
            if (await StraightShot()) return true;
            if (await MiserysEnd()) return true;
            if (await Bloodletter()) return true;
            if (await QuickNock()) return true;
            if (await VenomousBite()) return true;
            if (await WindBite()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL42() { return await CombatLvL40(); }
        public override async Task<bool> CombatLvL44() { return await CombatLvL40(); }
        public override async Task<bool> CombatLvL46()
        {
            if (await Featherfoot()) return true;
            if (await SecondWind()) return true;
            if (await Invigorate()) return true;
            if (await Shadowbind()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await BardSpells.HawksEye.Buff()) return true;
            if (await BardSpells.Barrage.Buff()) return true;
            if (await BardSpells.CrossClass.InternalRelease.Buff()) return true;
            if (await BardSpells.CrossClass.BloodForBlood.Buff()) return true;
            if (await BardSpells.QuellingStrikes.Buff()) return true;
            if (await StraightShot()) return true;
            if (await MiserysEnd()) return true;
            if (await Bloodletter()) return true;
            if (await FlamingArrow()) return true;
            if (await RainOfDeath()) return true;
            if (await QuickNock()) return true;
            if (await VenomousBite()) return true;
            if (await WindBite()) return true;
            return await HeavyShot();
        }
        public override async Task<bool> CombatLvL48() { return await CombatLvL46(); }
        #endregion

        public override async Task<bool> CombatLvL50()
        {
            if (await Shadowbind()) return true;
            if (await SecondWind()) return true;
            if (await Featherfoot()) return true;
            if (await Invigorate()) return true;
            if (await Enliven()) return true;
            if (await BluntArrow()) return true;
            if (await BardSpells.CrossClass.InternalRelease.Buff()) return true;
            if (await BardSpells.RagingStrikes.Buff()) return true;
            if (await BardSpells.HawksEye.Buff()) return true;
            if (await BardSpells.Barrage.Buff()) return true;
            if (await BardSpells.CrossClass.BloodForBlood.Buff()) return true;
            if (await BardSpells.QuellingStrikes.Buff()) return true;
            if (await RepellingShot()) return true;
            if (await MiserysEnd()) return true;
            if (await Bloodletter()) return true;
            if (await FarShot()) return true;
            if (await BlastShot()) return true;
            if (await FlamingArrow()) return true;
            if (await StraightShot()) return true;
            if (await QuickNock()) return true;
            if (await RainOfDeath()) return true;
            if (await WideVolley()) return true;
            if (await WindBite()) return true;
            if (await VenomousBite()) return true;
            if (await MultiDot(BardSpells.Windbite)) return true;
            if (await MultiDot(BardSpells.VenomousBite)) return true;
            if (await HeavyShot()) return true;

            return true;
        }

        #region Combat Abilities
        #region Extras
        private async Task<bool> Swiftsong()
        {
            if (MovementManager.IsMoving || Core.Player.HasAura(BardSpells.Swiftsong.Name))
                return false;

            return await BardSpells.Swiftsong.Cast();
        }
        #endregion
        #region Combat
        private async Task<bool> RepellingShot()
        {
            if (Core.Player.CurrentTarget.Location.Distance(Core.Player.Location) < 5)
                return false;

            return await BardSpells.RepellingShot.Cast();
        }
        private async Task<bool> Bloodletter()
        {
            return await BardSpells.Bloodletter.Cast();
        }
        private async Task<bool> MiserysEnd()
        {
            return await BardSpells.MiserysEnd.Cast();
        }
        private async Task<bool> StraightShot()
        {
            if (Core.Player.HasAura("Straighter Shot") || !Core.Player.HasAura(BardSpells.StraightShot.Name))
                return await BardSpells.StraightShot.Cast();
         
            return false;
        }
        private async Task<bool> VenomousBite()
        {
            if (!Core.Player.CurrentTarget.HasAura(BardSpells.VenomousBite.Name, true, 2000))
                return await BardSpells.VenomousBite.Cast();

            return false;

        }
        private async Task<bool> WindBite()
        {
            if (!Core.Player.CurrentTarget.HasAura(BardSpells.Windbite.Name, true, 2000))
                return await BardSpells.Windbite.Cast();

            return false;
   
        }
        private async Task<bool> HeavyShot()
        {
            return await BardSpells.HeavyShot.Cast();                      
        }
        #endregion
        #region AOE
        private async Task<bool> FlamingArrow()
        {
            return await BardSpells.FlamingArrow.CastOnLocation();
        }
        private async Task<bool> WideVolley()
        {
            if (Core.Player.CurrentTPPercent < 30)
                return false;

            if (Helpers.EnemiesNearTarget(5) >= 3)
                return await BardSpells.WideVolley.Cast();

            return false;
        }
        private async Task<bool> RainOfDeath()
        {
            if (Core.Player.HasAura("Downpour Of Death"))
                return await BardSpells.RainOfDeath.Cast();

            return false;
        }
        private async Task<bool> QuickNock()
        {
            if (Core.Player.HasAura("Quicker Nock"))
                return await BardSpells.QuickNock.Cast();

            return false;
        }
        #endregion
        #region PVP
        private async Task<bool> FarShot()
        {
            return await BardSpells.PvP.Farshot.Cast();
        }
        private async Task<bool> BlastShot()
        {
            return await BardSpells.PvP.BlastShot.Cast();
        }
        private async Task<bool> Enliven()
        {
            if (Core.Player.CurrentTPPercent < 50)
                return await BardSpells.PvP.Enliven.Cast();

            return false;
        }
        #endregion
        #region Defensive
        private async Task<bool> SecondWind()
        {
            if (Core.Player.CurrentHealthPercent < 50)
                return await BardSpells.CrossClass.SecondWind.Buff();

            return false;
        }
        private async Task<bool> Invigorate()
        {
            if (Core.Player.CurrentTPPercent < 50)
                return await BardSpells.CrossClass.Invigorate.Buff();

            return false;
        }
        private async Task<bool> Featherfoot()
        {
            if (Core.Player.CurrentHealthPercent < 60 && Core.Player.CurrentTarget.Location.Distance(Core.Player.Location) < 5)
                return await BardSpells.CrossClass.Featherfoot.Buff();

            return false;
        }
        private async Task<bool> Shadowbind()
        {
            var unit = (from a in GameObjectManager.GetObjectsOfType<BattleCharacter>()
                        where a.Distance(Core.Player) < 5
                        where a.CurrentTargetId == Core.Player.ObjectId

                        select a).FirstOrDefault();


            if (unit != null)
            {
                await BardSpells.Shadowbind.Cast();
            }
            {
                return false;
            }
        }
        #endregion
        #region Interrupt
        private async Task<bool> BluntArrow()
        {
            List<string> spells = new List<string> { ConjurerSpells.CureII.Name, ConjurerSpells.Medica.Name, ConjurerSpells.MedicaII.Name, ArcanistSpells.Physick.Name, ScholarSpells.Adloquium.Name };

            var unit = (from a in GameObjectManager.GetObjectsOfType<BattleCharacter>()
                        where a.CanAttack
                        where a.Distance(Core.Player) < 25
                        where a.IsCasting && spells.Contains(a.SpellCastInfo.SpellData.Name)
                        select a).FirstOrDefault();


            if (unit != null)
            {
                await BardSpells.BluntArrow.Cast(unit);
                Logging.Write(Colors.OrangeRed, "[MoreDots] Interrupting " + unit.Name);
            }
            {
                return false;
            }
        }
        #endregion
        #region MultiDot
        private async Task<bool> MultiDot(Spell spell)
        {
            if (Core.Player.CurrentTarget.CurrentHealthPercent > 50)
                return false;

            var unit = (from a in GameObjectManager.GetObjectsOfType<BattleCharacter>()
                        orderby a.CurrentHealth ascending
                        where a.CurrentHealth > 1000
                        where Actionmanager.CanCast(spell.Name, a)
                        select a).FirstOrDefault();


            if (unit != null)
            {
                await spell.Cast(unit);
            }
            {
                return false;
            }
        }
        #endregion
        #endregion
    }
}
